package simpleserver;

import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.ObjectInputStream;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.apache.commons.io.FileUtils;

public class VerySimpleServer {

	static boolean copyFullFolder = true;

	private int serverPort;
	private ServerSocket serverSock = null;

	public VerySimpleServer(int serverPort) {
		this.serverPort = serverPort;

		try {
			serverSock = new ServerSocket(serverPort);
		} catch (IOException e) {
			e.printStackTrace(System.err);
		}
	}

	public void handleConnection(InputStream sockInput) {

		System.out.println("HANDLE CONNECTION ANGESTOSSEN");
		ObjectInputStream ois;

		try {
			ois = new ObjectInputStream(sockInput);

			try {
				byte[] cla = (byte[]) ois.readObject();

				FileUtils.writeByteArrayToFile(new File(
						"bin/simpleserver/MobAgent.class"), cla);
			} catch (ClassNotFoundException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}

			try {
				List<String> lis;
				lis = (List<String>) ois.readObject();
				FileUtils.writeLines(new File(
						"MyFiles/meine_naechsten_Ziele.txt"), lis);
			} catch (ClassNotFoundException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
			try {
				List<String> lis;
				lis = (List<String>) ois.readObject();
				FileUtils.writeLines(new File("MyFiles/Mitgenommen.txt"), lis);
			} catch (ClassNotFoundException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}

			if (copyFullFolder == true) {
				try {
					List<Map<String, byte[]>> folderlist;
					folderlist = (List<Map<String, byte[]>>) ois.readObject();
					convertListToFolder(folderlist);

				} catch (ClassNotFoundException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
			}

			System.out.println("handle done");
			runFirstAgent(false);

		} catch (IOException e1) {
			// TODO Auto-generated catch block
			e1.printStackTrace();
		}
	}

	public boolean convertListToFolder(List<Map<String, byte[]>> inputlist) {

		for (Map<String, byte[]> entry : inputlist) {

			Set<String> set = entry.keySet();

			for (String s : set) {
				File currfile = new File(s);
				try {
					FileUtils.writeByteArrayToFile(currfile, entry.get(s));
				} catch (IOException e) {
					e.printStackTrace();
					System.out
							.println("convertListToFolder: Dateien konten nicht korrekt wieder hergestellt werden");
					return false;
				}
			}
		}
		return true;
	}

	public void waitForConnections() {
		Socket sock = null;
		InputStream sockInput = null;
		while (true) {
			try {
				// This method call, accept(), blocks and waits
				// (forever if necessary) until some other program
				// opens a socket connection to our server. When some
				// other program opens a connection to our server,
				// accept() creates a new socket to represent that
				// connection and returns.
				System.out.println("SERVER: Waiting for connection");
				sock = serverSock.accept();
				System.err.println("Server: Have accepted new socket.");

				// From this point on, no new socket connections can
				// be made to our server until we call accept() again.

				sockInput = sock.getInputStream();
				System.out.println(sockInput);
			} catch (IOException e) {
				e.printStackTrace(System.err);
			}

			handleConnection(sockInput);

			try {
				System.err.println("Closing socket.");
				sock.close();
			} catch (Exception e) {
				System.err.println("Exception while closing socket.");
				e.printStackTrace(System.err);
			}

			System.err
					.println("Finished with socket, waiting for next connection.");
		}
	}

	public void runFirstAgent(boolean b) {
		System.out.println("Start first Agent");
		Object o;

		String path1 = "simpleserver.MobAgent";
		String path2 = "MobAgent";

		try {
			if (b == true) {
				ClassLoader c1 = new NewCustomClassLoader();
				System.out.println("b = true");
				o = c1.loadClass(path1).newInstance();
			} else {
				System.out.println("b = false");
				// ------------------------
				ClassLoader c2 = new NewCustomClassLoader();
				o = c2.loadClass(path1).newInstance();
			}
			System.out.println(o.getClass());
			try {
				Class<?> c = o.getClass();
				System.out.println("try to invoke method");
				Method m = c.getMethod("agentWork");
				m.invoke(o);
				System.out.println("method invoked");
			} catch (IllegalArgumentException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			} catch (SecurityException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			} catch (InvocationTargetException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			} catch (NoSuchMethodException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		} catch (InstantiationException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IllegalAccessException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (ClassNotFoundException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}

	}

	public static void main(String argv[]) {

		int port = 54000;
		VerySimpleServer server = new VerySimpleServer(port);

		// ClassLoader c1 = new NewCustomClassLoader();

		server.runFirstAgent(true);
		server.waitForConnections();

		// System.out.println(System.getProperty("java.class.path"));

	}
}